home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
sprender.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
16KB
|
799 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* sprender -
* Generic gl rendering stuff.
*
* Paul Haeberli - 1990
*/
#include "stdio.h"
#include "gl.h"
#include "math.h"
#include "vect.h"
#include "render.h"
#include "acc.h"
#include "sgiobj.h"
#include "trilist.h"
static objidcolor();
#define ACCSCALE (0.25)
typedef struct rendobj {
struct rendobj *next;
sgiobj *obj;
float matrix[4][4];
int isdiff, isspec, istrans;
vect diffc, specc, transc;
int diffmap, specmap;
} rendobj;
static rendobj *orendlist;
static rendobj curshader;
static rendobj *trendlist;
static int renderq = RQ_SHADED;
static int demo, firsted;
static int doclear = 1;
static char backimagename[256];
demomode(m)
int m;
{
demo = m;
if(demo) {
singlebuffer();
gconfig();
} else {
doublebuffer();
gconfig();
}
}
renderquality(q)
int q;
{
renderq = q;
}
getrenderquality()
{
return renderq;
}
backimage(name)
char *name;
{
strcpy(backimagename,name);
}
renderclear(f)
{
doclear = f;
}
static clearscreen(how)
int how;
{
blendfunction(BF_ONE,BF_ZERO);
zwritemask(0x00ffffff);
zclear();
zbuffer(0);
settexture(0);
switch(renderq) {
case RQ_LINES:
cpack(0x00ffffff);
clear();
break;
case RQ_NORMALS:
cpack(0x00808080);
clear();
break;
default:
if(strlen(backimagename)>0) {
drawback(backimagename);
} else {
cpack(0x00ffffff);
clear();
}
break;
}
}
rendershader(diffmap,diffc,specmap,specc,transc)
int diffmap;
vect *diffc;
int specmap;
vect *specc;
vect *transc;
{
float minval;
minval = 0.5/255.0;
curshader.diffmap = diffmap;
if(diffc) {
curshader.diffc = *diffc;
if(diffc->x>minval || diffc->y>minval || diffc->z>minval)
curshader.isdiff = 1;
else
curshader.isdiff = 0;
} else {
#ifdef OLDWAY
vone(&curshader.diffc);
curshader.isdiff = 1;
#else
vzero(&curshader.diffc);
curshader.isdiff = 0;
#endif
}
curshader.specmap = specmap;
if(specc) {
curshader.specc = *specc;
if(specc->x>minval || specc->y>minval || specc->z>minval)
curshader.isspec = 1;
else
curshader.isspec = 0;
} else {
vone(&curshader.specc);
curshader.isspec = 1;
}
if(transc && (transc->x>minval || transc->y>minval || transc->z>minval)) {
curshader.transc = *transc;
curshader.istrans = 1;
} else {
vzero(&curshader.transc);
curshader.istrans = 0;
}
}
printshader()
{
printf("isdiff: %d ",curshader.isdiff);
vprint(&curshader.diffc);
printf("isspec: %d ",curshader.isspec);
vprint(&curshader.specc);
printf("istrans: %d ",curshader.istrans);
vprint(&curshader.transc);
printf("diffmap %d, specmap %d\n",curshader.diffmap,curshader.specmap);
}
renderobj(obj)
sgiobj *obj;
{
rendobj *robj;
robj = (rendobj *)mymalloc(sizeof(rendobj));
robj->obj = obj;
getmatrix(robj->matrix);
robj->isdiff = curshader.isdiff;
robj->isspec = curshader.isspec;
robj->istrans = curshader.istrans;
robj->diffc = curshader.diffc;
robj->specc = curshader.specc;
robj->transc = curshader.transc;
robj->diffmap = curshader.diffmap;
robj->specmap = curshader.specmap;
if(robj->istrans) {
robj->next = trendlist;
trendlist = robj;
} else {
robj->next = orendlist;
orendlist = robj;
}
}
beginrender()
{
rendobj *nobj;
if(!firsted) {
materialname("/usr/people/paul/gfx/render.mat");
lightsname("/usr/people/paul/gfx/render.lgt");
shadingoff();
firsted = 1;
}
while(orendlist) {
nobj = orendlist->next;
free(orendlist);
orendlist = nobj;
}
while(trendlist) {
nobj = trendlist->next;
free(trendlist);
trendlist = nobj;
}
pushmatrix();
}
endrender()
{
rendobj *robj;
int objid;
unsigned long tr, tg, tb, c;
unsigned long rr, rg, rb;
int dospec, dodiff;
vect v, vdif, vspec;
float projmat[4][4], psmat[4][4];
if(doclear)
clearscreen(renderq);
popmatrix();
if(demo)
sleep(1);
pushmatrix();
switch(renderq) {
case RQ_NORMALS:
zbuffer(1);
zwritemask(0x00ffffff);
backface(1);
blendfunction(BF_ONE,BF_ZERO);
settexture(0);
robj = orendlist;
while(robj) {
loadmatrix(robj->matrix);
drawnormobj(robj->obj,robj->matrix);
robj = robj->next;
}
robj = trendlist;
while(robj) {
loadmatrix(robj->matrix);
drawnormobj(robj->obj,robj->matrix);
robj = robj->next;
}
break;
case RQ_PSOUT:
pspolyrender();
break;
case RQ_OBJID:
zbuffer(1);
zwritemask(0x00ffffff);
backface(1);
blendfunction(BF_ONE,BF_ZERO);
settexture(0);
objid = 0;
robj = orendlist;
while(robj) {
objidcolor(objid++);
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS);
robj = robj->next;
}
robj = trendlist;
while(robj) {
objidcolor(objid++);
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS);
robj = robj->next;
}
break;
case RQ_LINES:
switch(gfxmachine()) {
MACH4DVGX:
linesmooth(SML_ON|SML_SMOOTHER|SML_END_CORRECT);
blendfunction(BF_SA,BF_MSA);
break;
default:
linesmooth(SML_OFF);
blendfunction(BF_ONE,BF_ZERO);
break;
}
zbuffer(1);
zwritemask(0x00000000);
backface(0);
cpack(0x80000000);
settexture(0);
robj = orendlist;
while(robj) {
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_LINES);
robj = robj->next;
}
robj = trendlist;
while(robj) {
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_LINES);
robj = robj->next;
}
linesmooth(SML_OFF);
break;
case RQ_GLSHADED:
zbuffer(1);
zwritemask(0x00ffffff);
backface(1);
blendfunction(BF_ONE,BF_ZERO);
settexture(0);
shadingon();
robj = orendlist;
while(robj) {
lmcolor(LMC_SPECULAR);
c3f((float*)&robj->specc);
lmcolor(LMC_DIFFUSE);
if(robj->diffmap) {
textureaverage(robj->diffmap,&vdif);
vmult(&robj->diffc,&vdif,&vdif);
c3f((float*)&vdif);
} else {
c3f((float*)&robj->diffc);
}
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS);
robj = robj->next;
}
zwritemask(0x00000000);
backface(0);
blendfunction(BF_ONE,BF_ONE);
vzero(&vdif);
robj = trendlist;
while(robj) {
lmcolor(LMC_DIFFUSE);
c3f((float*)&vdif);
lmcolor(LMC_SPECULAR);
vspec = robj->specc;
c3f((float*)&vspec);
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS);
robj = robj->next;
}
lmcolor(LMC_COLOR);
shadingoff();
break;
case RQ_SHADED:
zbuffer(1);
zwritemask(0x00ffffff);
backface(1);
settexture(0);
robj = orendlist;
while(robj) {
if(robj->isspec && robj->specmap)
dospec = 1;
else
dospec = 0;
if(robj->isdiff)
dodiff = 1;
else
dodiff = 0;
if(dodiff) {
blendfunction(BF_ONE,BF_ZERO);
shadingon();
lmcolor(LMC_DIFFUSE);
tmc3f((float*)&robj->diffc);
settexture(robj->diffmap);
loadmatrix(robj->matrix);
if(robj->diffmap)
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS|DRAW_UVS);
else
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS);
lmcolor(LMC_COLOR);
shadingoff();
}
if(dospec) {
if(dodiff)
blendfunction(BF_ONE,BF_ONE);
else
blendfunction(BF_ONE,BF_ZERO);
tmc3f((float*)&robj->specc);
settexture(robj->specmap);
loadmatrix(robj->matrix);
drawenvobj(robj->obj,robj->matrix);
}
robj = robj->next;
}
if(demo)
sleep(1);
zwritemask(0x00000000); /* draw specular */
backface(0);
blendfunction(BF_ONE,BF_ONE);
robj = trendlist;
while(robj) {
if(robj->isspec && robj->specmap) {
v = robj->specc;
if(vsignif(&v)) {
tmc3f((float*)&v);
settexture(robj->specmap);
loadmatrix(robj->matrix);
drawenvobj(robj->obj,robj->matrix);
}
}
robj = robj->next;
}
if(demo)
sleep(1);
backface(1);
settexture(0);
blendfunction(BF_ZERO,BF_SC);
#ifdef OLDWAY
blendfunction(BF_ZERO,BF_SA);
#endif
wmpack(0x00ffffff);
robj = trendlist;
while(robj) {
tr = 255.0*robj->transc.x+0.49; /* dim area */
tg = 255.0*robj->transc.y+0.49;
tb = 255.0*robj->transc.z+0.49;
c = (tb<<16)+(tg<<8)+(tr<<0);
cpack(c);
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS);
#ifdef OLDWAY
tr = 255.0*robj->transc.x+0.49; /* dim area */
tg = 255.0*robj->transc.y+0.49;
tb = 255.0*robj->transc.z+0.49;
loadmatrix(robj->matrix);
if(tr == tg && tg == tb) {
wmpack(0x00ffffff);
cpack(tr<<24);
drawsgiobj(robj->obj,DRAW_POINTS);
} else {
wmpack(0x000000ff);
cpack(tr<<24);
drawsgiobj(robj->obj,DRAW_POINTS);
wmpack(0x0000ff00);
cpack(tg<<24);
drawsgiobj(robj->obj,DRAW_POINTS);
wmpack(0x00ff0000);
cpack(tb<<24);
drawsgiobj(robj->obj,DRAW_POINTS);
}
#endif
robj = robj->next;
}
if(demo)
sleep(1);
zwritemask(0x00ffffff); /* get closest zee's */
backface(1);
blendfunction(BF_ONE,BF_ZERO);
wmpack(0x00000000);
robj = trendlist;
while(robj) {
loadmatrix(robj->matrix);
drawsgiobj(robj->obj,DRAW_POINTS);
robj = robj->next;
}
zwritemask(0x00000000); /* add in specular on front */
backface(1);
blendfunction(BF_ONE,BF_ONE);
wmpack(0x00ffffff);
robj = trendlist;
while(robj) {
if(robj->specmap) {
v.x = robj->specc.x*(1.0-robj->transc.x);
v.y = robj->specc.y*(1.0-robj->transc.y);
v.z = robj->specc.z*(1.0-robj->transc.z);
if(vsignif(&v)) {
tmc3f((float*)&v);
settexture(robj->specmap);
loadmatrix(robj->matrix);
drawenvobj(robj->obj,robj->matrix);
}
}
robj = robj->next;
}
zwritemask(0x00000000); /* add in diffuse on front */
backface(1);
blendfunction(BF_ONE,BF_ONE);
wmpack(0x00ffffff);
robj = trendlist;
while(robj) {
if(robj->isdiff) {
vdif.x = robj->diffc.x*(1.0-robj->transc.x);
vdif.y = robj->diffc.y*(1.0-robj->transc.y);
vdif.z = robj->diffc.z*(1.0-robj->transc.z);
if(vsignif(&v)) {
tmc3f((float*)&vdif);
settexture(robj->diffmap);
loadmatrix(robj->matrix);
if(robj->diffmap)
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS|DRAW_UVS);
else
drawsgiobj(robj->obj,DRAW_POINTS|DRAW_NORMALS);
}
}
robj = robj->next;
}
if(demo)
sleep(1);
break;
}
popmatrix();
}
static objidcolor(id)
int id;
{
long c;
int i, rbit, gbit, bbit;
id++;
c = 0;
for(i=0; i<8; i++) {
rbit = (id>>((3*i)+0))&1;
gbit = (id>>((3*i)+1))&1;
bbit = (id>>((3*i)+2))&1;
c |= (rbit<<(7-i))+(gbit<<(15-i))+(bbit<<(23-i));
}
cpack(c);
}
makearray(func,nx,ny,space)
int (*func)();
int nx, ny;
float space;
{
int x, y;
float tx, ty;
for(y=0; y<ny; y++) {
for(x=0; x<nx; x++) {
tx = x-(nx-1)/2.0;
ty = y-(ny-1)/2.0;
pushmatrix();
translate(tx*space,0.0,ty*space);
func();
popmatrix();
}
}
}
gfxinit()
{
zbuffer(1);
subpixel(1);
RGBmode();
doublebuffer();
gconfig();
matinit();
cpack(0x808080);
clear();
swapbuffers();
}
vsignif(v)
vect *v;
{
if(v->x>(1.0/255.0))
return 1;
if(v->y>(1.0/255.0))
return 1;
if(v->z>(1.0/255.0))
return 1;
return 0;
}
/*
* accbuff stuff follows
*
*
*/
static char accfile[256];
doaccbuf(drawfunc,filename)
int (*drawfunc)();
char *filename;
{
FILE *lensf;
FILE *accf;
ACCPNTS *pixlpnts;
ACCPNTS *lenspnts;
int i, npasses;
float xpix, ypix, xshift, yshift;
strcpy(accfile,filename);
pixlpnts = openpnts("/usr/people/paul/gfx/acc/pixl.pnts");
lenspnts = openpnts("/usr/people/paul/gfx/acc/lens.pnts");
npasses = numpnts(pixlpnts);
printf("npasses is %d\n",npasses);
myacsize(16);
gconfig();
myacbuf(AC_CLEAR,0.0);
tpercentdone(0.0);
for(i=0; i<npasses; i++) {
getaccpnt(pixlpnts,i,&xpix,&ypix);
getaccpnt(lenspnts,i,&xshift,&yshift);
xshift -= 0.5;
yshift -= 0.5;
accset(xpix,ypix,xshift,yshift);
drawfunc(i/(npasses-1.0));
myacbuf(AC_ACCUMULATE,ACCSCALE);
tpercentdone(100.0*i/(npasses-1));
#ifdef USEGLACCBUF
myacbuf(AC_RETURN,1.0/(ACCSCALE*(i+1)));
swapbuffers();
#endif
}
myacbuf(AC_RETURN,1.0/(ACCSCALE*npasses));
swapbuffers();
myacsize(0);
gconfig();
}
static int accfirsted;
myacsize(nbits)
int nbits;
{
#ifdef USEGLACCBUF
acsize(nbits);
#endif
}
myacbuf(func,value)
int func;
float value;
{
long xsize, ysize;
#ifdef USEGLACCBUF
acbuf(func,value);
#else
if(!accfirsted) {
getsize(&xsize,&ysize);
newacc(xsize,ysize);
accfirsted = 1;
}
switch(func) {
case AC_CLEAR:
clearacc();
break;
case AC_ACCUMULATE:
addtoacc();
break;
case AC_RETURN:
saveacc(accfile);
break;
}
#endif
}
/*
* pspoly render follows . . .
*
*/
static FILE *tlfile;
static float *psprojmat;
#define TRITOL (0.000000001)
tocpack(v)
float v[4];
{
int r, g, b, a;
unsigned long c;
r = 255.0*v[0];
g = 255.0*v[1];
b = 255.0*v[2];
a = 255.0*v[3];
c = (a<<24) + (b<<16) + (g<<8) + (r<<0);
return c;
}
static transtri;
static pstrifunc(p0,p1,p2)
long *p0, *p1, *p2;
{
vect tp0, tp1, tp2, n;
vect pj0, pj1, pj2, pn;
vect t, c0, c1, c2;
float a;
trilisttri tri;
if(transtri)
a = 0.0;
else
a = 1.0;
xformvert4(psprojmat,p0+OFFSET_POINT,&tp0);
xformvert4(psprojmat,p1+OFFSET_POINT,&tp1);
xformvert4(psprojmat,p2+OFFSET_POINT,&tp2);
if(trinormal(&tp0,&tp1,&tp2,&n,TRITOL)) {
pj0.x = tp0.x/tp0.w;
pj0.y = tp0.y/tp0.w;
pj0.z = tp0.z/tp0.w;
pj1.x = tp1.x/tp1.w;
pj1.y = tp1.y/tp1.w;
pj1.z = tp1.z/tp1.w;
pj2.x = tp2.x/tp2.w;
pj2.y = tp2.y/tp2.w;
pj2.z = tp2.z/tp2.w;
tenv(p0+OFFSET_NORMAL,p0+OFFSET_POINT,&t);
fakettoc(&t,&c0);
tenv(p1+OFFSET_NORMAL,p1+OFFSET_POINT,&t);
fakettoc(&t,&c1);
tenv(p2+OFFSET_NORMAL,p2+OFFSET_POINT,&t);
fakettoc(&t,&c2);
c0.w = c1.w = c2.w = a;
tri.x0 = pj0.x;
tri.y0 = pj0.y;
tri.z0 = -pj0.z;
tri.c0 = tocpack(&c0);
tri.x1 = pj1.x;
tri.y1 = pj1.y;
tri.z1 = -pj1.z;
tri.c1 = tocpack(&c1);
tri.x2 = pj2.x;
tri.y2 = pj2.y;
tri.z2 = -pj2.z;
tri.c2 = tocpack(&c2);
fwrite(&tri,sizeof(trilisttri),1,tlfile);
}
}
pspolyrender()
{
rendobj *robj;
float projmat[4][4], psmat[4][4];
short magic;
tlfile = fopen("/tmp/gscript.tl","w");
if(!tlfile) {
fprintf(stderr,"render: can't open trilist file\n");
return;
}
magic = TLMAGIC;
fwrite(&magic,sizeof(short),1,tlfile);
robj = orendlist;
mmode(MPROJECTION);
getmatrix(projmat);
mmode(MVIEWING);
transtri = 0;
while(robj) {
matrixmult(projmat,robj->matrix,psmat);
psprojmat = &psmat[0][0];
tenvmat(&robj->matrix[0][0]);
tmc3f((float*)&robj->specc);
settexture(robj->specmap);
applytotris(robj->obj,pstrifunc);
robj = robj->next;
}
transtri = 1;
robj = trendlist;
while(robj) {
matrixmult(projmat,robj->matrix,psmat);
psprojmat = &psmat[0][0];
tenvmat(&robj->matrix[0][0]);
tmc3f((float*)&robj->specc);
settexture(robj->specmap);
applytotris(robj->obj,pstrifunc);
robj = robj->next;
}
fclose(tlfile);
}